<?php
/**
 * Created by xun at 2021/4/26
 */
namespace console\controllers;

use common\helpers\BtAPI;
use common\models\c2\entity\BtResource;
use yii\console\Controller;

class BtMonitorController extends Controller
{

    // public $default = [
    //     '192.168.199.132' => [
    //         'id' => '测试服务器(192.168.199.132)',
    //         'name' => '测试服务器(192.168.199.132)',
    //         'key' => 'EbSx06rH0Rmg4d4WoJOHGpTceuGfEtWX',
    //         'panel' => 'http://192.168.199.132:8888',
    //         'last_alert_time' => [
    //             'disk' => 0,
    //             'cpu' => 0,
    //             'mem' => 0,
    //             'load' => 0,
    //         ],
    //     ],
    //     '47.106.233.152' => [
    //         'name' => '国内正式服务器(47.106.233.152)',
    //         'key' => 'xJYPOEyoKGnq8WWq4HRVXiUWUdDGLCGU',
    //         'panel' => 'http://47.106.233.152:8888',
    //         'last_alert_time' => [
    //             'disk' => 0,
    //             'cpu' => 0,
    //             'mem' => 0,
    //             'load' => 0,
    //         ],
    //     ],
    //     '3.139.131.103' => [
    //         'name' => '国外正式服务器(3.139.131.103)',
    //         'key' => 'Z3DBKzcrj4jHs3oDX31zLSbnH5q5YRsw',
    //         'panel' => 'http://3.139.131.103:39600',
    //         'last_alert_time' => [
    //             'disk' => 0,
    //             'cpu' => 0,
    //             'mem' => 0,
    //             'load' => 0,
    //         ],
    //     ]
    // ];
    //
    // public $bt_res_expire = 60 * 60 * 24;

    public $time = 0;

    public function init()
    {
        parent::init(); // TODO: Change the autogenerated stub
        $this->time = time();
    }

    /**
     * Renders the index view for the module
     * @return string
     */
    public function actionIndex()
    {
        $config = json_decode(\Yii::$app->redis->get('bt_server'), true);
        $bt_res_expire = \Yii::$app->settings->get('bt_res_expire_time', 60 * 60 * 24 * 30);
        $resource_data = [];
        foreach ($config as $server_key => $conf) {
            $entity = new BtAPI($conf['panel'], $conf['key']);
            $data = json_decode($entity->GetNetWork(), true);
            // print_r($data);
            if ($data && isset($data['cpu']) && isset($data['mem']) && isset($data['load']) && isset($data['disk'])) {

                \Yii::$app->redis->lpush($this->formatKey($server_key, 'cpu'), $this->formatVal($data['cpu'][0]));
                \Yii::$app->redis->expire($this->formatKey($server_key, 'cpu'), $bt_res_expire);

                \Yii::$app->redis->lpush($this->formatKey($server_key, 'up'), $this->formatVal($data['up']));
                \Yii::$app->redis->expire($this->formatKey($server_key, 'up'), $bt_res_expire);

                \Yii::$app->redis->lpush($this->formatKey($server_key, 'down'), $this->formatVal($data['down']));
                \Yii::$app->redis->expire($this->formatKey($server_key, 'down'), $bt_res_expire);

                $mem = round($data['mem']['memTotal'] / $data['mem']['memRealUsed'], 2) * 10;
                \Yii::$app->redis->lpush($this->formatKey($server_key, 'mem'), $this->formatVal($mem));
                \Yii::$app->redis->expire($this->formatKey($server_key, 'mem'), $bt_res_expire);

                $load = round($data['load']['one'] * 100 / $data['load']['max'], 1);
                \Yii::$app->redis->lpush($this->formatKey($server_key, 'load'), $this->formatVal($load));
                \Yii::$app->redis->expire($this->formatKey($server_key, 'load'), $bt_res_expire);

                $data['request_time'] = $this->time;
                $data['label'] = $conf['name'];
                $resource_data[$server_key] = $data;
            } else {
                \Yii::info($data);
            }
        }
        \Yii::$app->redis->set('bt_resource_data', json_encode($resource_data));
        // $flag = $this->check($resource_data, $config);
        // if ($flag) {
        //     \Yii::$app->settings->set('bt_server', json_encode($config, JSON_UNESCAPED_UNICODE));
        //     \Yii::$app->settings->set('bt_resource_data', json_encode($resource_data));
        // }
    }

    public function formatKey(...$val)
    {
        return "bt-" . $val[0] .  '-' . $val[1];
    }

    public function formatVal(...$val)
    {
        // return $this->time . ":" . $val[0];
        return $val[0];
    }

    public function check(&$data, &$config)
    {
        $bt_max_cap = \Yii::$app->settings->get('bt_max_cap', 200000);
        $bt_api_freq = \Yii::$app->settings->get('bt_api_freq', 10000);
        $bt_alert_interval = \Yii::$app->settings->get('bt_alert_interval', 3600);
        $cap = $bt_max_cap / $bt_api_freq;
        $now = time();


        foreach ($data as $server_key => $datum) {

            // 满载
            if (count($data[$server_key]) >= $cap) {
                $log = '';

                // 硬盘只需要检查最后一条
                $lastData = end($datum);
                foreach ($lastData['disk'] as $datum1) {
                    if (intval($datum1['size'][3]) > 80) {
                        // 通知叮叮
                        if ($now - $config[$server_key]['last_alert_time']['disk'] > $bt_alert_interval) {
                            $log .= $this->ding('fitdays', sprintf("%s的硬盘使用已达到%s，请处理。", $server_key, $datum1['size'][3]));
                            $config[$server_key]['last_alert_time']['disk'] = $now;
                        }
                    }
                }

                // 检查其他资源
                $cpu_status = 0;
                $mem_status = 0;
                $load_status = 0;
                foreach ($datum as $item) {
                    if ($item['cpu'][0] >= 90) {
                        $cpu_status++;
                    }
                    if ($item['mem']['memFree'] <= 512) {
                        $mem_status++;
                    }
                    if ($item['load']['one'] >= $item['load']['safe'] * 1.2) {
                        $load_status++;
                    }
                }
                if ($cpu_status > $cap * 0.8) {
                    if ($now - $config[$server_key]['last_alert_time']['cpu'] > $bt_alert_interval) {
                        $log .= $this->ding('fitdays', sprintf("%s的cpu使用率持续过高，请处理。", $server_key));
                        $config[$server_key]['last_alert_time']['cpu'] = $now;
                    }
                }
                if ($mem_status > $cap * 0.8) {
                    if ($now - $config[$server_key]['last_alert_time']['mem'] > $bt_alert_interval) {
                        $log .= $this->ding('fitdays', sprintf("%s的内存使用率持续过高，请处理。", $server_key));
                        $config[$server_key]['last_alert_time']['mem'] = $now;
                    }
                }
                if ($load_status > $cap * 0.8) {
                    if ($now - $config[$server_key]['last_alert_time']['load'] > $bt_alert_interval) {
                        $log .= $this->ding('fitdays', sprintf("%s的负载率持续过高，请处理。", $server_key));
                        $config[$server_key]['last_alert_time']['load'] = $now;
                    }
                }

                // 保存
                $model = new BtResource();
                $model->setAttributes([
                    'server_id' => $server_key,
                    'save_time' => $now,
                    'content' => json_encode($data[$server_key]),
                    'log' => $log,
                ]);
                $model->save();

                // 清空
                $data[$server_key] = [];
            }
        }
        return true;
    }

    // 推送叮叮
    public function ding($topic, $datas)
    {

        return $datas;
        $endpoint = 'cn-shenzhen.log.aliyuncs.com';
        $accessKeyId = 'LTAI4G3NncgK1zMevFQQdkWu';
        $accessKey = 'ZyJwS8vX0tO8YsgwmbGg3Cn98lhHSf';
        $project = 'fitdays-cn-test-log';
        $logstore = 'fitdays-cn-test-logstore';
        $token = "";

        $client = new \Aliyun_Log_Client($endpoint, $accessKeyId, $accessKey, $token);

        $contents = array( // key-value pair
            'log_datas' => $datas,
        );
        $logItem = new \Aliyun_Log_Models_LogItem();
        $logItem->setTime(time());
        $logItem->setContents($contents);
        $logitems = array($logItem);
        $request = new \Aliyun_Log_Models_PutLogsRequest($project, $logstore, $topic, null, $logitems);

        try {
            return $client->putLogs($request);
        } catch (\Aliyun_Log_Exception $ex) {
            return $ex->getMessage();
        } catch (\Exception $ex) {
            return $ex->getMessage();
        }
    }

}